﻿using Domain.Entitys.FG;
using Domain.Entitys.Inv;
using Domain.Entitys.Sinv;
using Domain.IRepositorys.FG;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EFCore.Repositorys.FG
{
    public class FG_Finished_Goods_StoreRepository : IFG_Finished_Goods_StoreRepository
    {
        private readonly MyDbContext myDbContext;

        public FG_Finished_Goods_StoreRepository(MyDbContext myDbContext)
        {
            this.myDbContext = myDbContext;
        }

        /// <summary>
        /// 添加成品入库信息及其详情
        /// </summary>
        /// <param name="fG_Finished_Goods_Store"></param>
        /// <param name="fG_Finished_Goods_Store_Details"></param>
        /// <returns></returns>
        public async Task<int> FG_Finished_Goods_StoreAddAsync(FG_Finished_Goods_Store fG_Finished_Goods_Store, List<FG_Finished_Goods_Store_Details> fG_Finished_Goods_Store_Details)
        {
            using var transaction = await myDbContext.Database.BeginTransactionAsync();
            try
            {
                //添加成品入库信息
                await myDbContext.FG_Finished_Goods_Store.AddAsync(fG_Finished_Goods_Store);
                await myDbContext.SaveChangesAsync();

                //添加成品入库明细
                foreach (var item in fG_Finished_Goods_Store_Details)
                {
                    item.Finished_goods_store_id = fG_Finished_Goods_Store.Finished_goods_store_id;
                    item.Finished_goods_store_code = fG_Finished_Goods_Store.Finished_goods_store_code;
                }
                await myDbContext.FG_Finished_Goods_Store_Details.AddRangeAsync(fG_Finished_Goods_Store_Details);

                //增加库存预计入库数量
                //var proCodes = fG_Finished_Goods_Store_Details.Select(f => f.Pro_code).Distinct().ToList();
                //var stocks = await myDbContext.inv_stock
                //    .Where(s => proCodes.Contains(s.pro_code))
                //    .ToDictionaryAsync(s => s.pro_code);
                var proCodes = fG_Finished_Goods_Store_Details.Select(d => d.Pro_code).Distinct().ToList();
                var locationCodes = fG_Finished_Goods_Store_Details.Select(d => d.Location_code).Distinct().ToList();
                var stockList = await myDbContext.inv_stock
                    .Where(s => proCodes.Contains(s.pro_code)
                        && locationCodes.Contains(s.Location_Code)
                        && fG_Finished_Goods_Store.Warehouse_code.Contains(s.Warehouse_Code)
                        && fG_Finished_Goods_Store.Zone_code.Contains(s.Zone_Code))
                    .GroupBy(x => x.pro_code)
                    .Select(g => g.OrderBy(x => x.Create_Time).First())//升序排序多组重复记录每组取第一条
                    .ToListAsync();

                // 字典1：以stock_id为键
                var stocksById = stockList.ToDictionary(s => s.stock_id);
                // 字典2：以pro_code为键映射到stock_id
                var stockIdByProCode = stockList.ToDictionary(s => s.pro_code, s => s.stock_id);

                foreach (var item in fG_Finished_Goods_Store_Details)
                {
                    if (stockIdByProCode.TryGetValue(item.Pro_code, out var stockId))
                    {
                        stocksById[stockId].Stock_planned_store_qty += item.Store_qty;
                        myDbContext.Entry(stocksById[stockId]).State = EntityState.Modified;
                    }
                }

                await myDbContext.SaveChangesAsync();
                await transaction.CommitAsync();
                return 1;
            }
            catch (Exception)
            {
                await transaction.RollbackAsync();
                return 0;
            }
        }

        /// <summary>
        /// 修改产品入库信息及其明细
        /// </summary>
        /// <param name="fG_Finished_Goods_Store"></param>
        /// <param name="fG_Finished_Goods_Store_Details"></param>
        /// <returns></returns>
        public async Task<int> FG_Finished_Goods_StoreUpdateAsync(FG_Finished_Goods_Store fG_Finished_Goods_Store, List<FG_Finished_Goods_Store_Details> fG_Finished_Goods_Store_Details)
        {
            using var transaction = await myDbContext.Database.BeginTransactionAsync();
            try
            {
                //修改成品入库信息
                FG_Finished_Goods_Store fG_Finished_Goods_Store1 = await myDbContext.FG_Finished_Goods_Store
                    .FirstOrDefaultAsync(f => f.Finished_goods_store_id == fG_Finished_Goods_Store.Finished_goods_store_id);
                fG_Finished_Goods_Store1.Finished_goods_store_time = fG_Finished_Goods_Store.Finished_goods_store_time;
                fG_Finished_Goods_Store1.Warehouse_code = fG_Finished_Goods_Store.Warehouse_code;
                fG_Finished_Goods_Store1.Warehouse_name = fG_Finished_Goods_Store.Warehouse_name;
                fG_Finished_Goods_Store1.Zone_code = fG_Finished_Goods_Store.Zone_code;
                fG_Finished_Goods_Store1.Zone_name = fG_Finished_Goods_Store.Zone_name;
                fG_Finished_Goods_Store1.Finished_goods_store_dept_id = fG_Finished_Goods_Store.Finished_goods_store_dept_id;
                fG_Finished_Goods_Store1.Finished_goods_store_rep_id = fG_Finished_Goods_Store.Finished_goods_store_rep_id;
                fG_Finished_Goods_Store1.Quality_testing_by = fG_Finished_Goods_Store.Quality_testing_by;
                fG_Finished_Goods_Store1.Quality_testing_status = fG_Finished_Goods_Store.Quality_testing_status;
                fG_Finished_Goods_Store1.Quality_testing_time = fG_Finished_Goods_Store.Quality_testing_time;
                fG_Finished_Goods_Store1.Update_by = fG_Finished_Goods_Store.Update_by;
                fG_Finished_Goods_Store1.Update_time = fG_Finished_Goods_Store.Update_time;
                myDbContext.Update(fG_Finished_Goods_Store1);
                await myDbContext.SaveChangesAsync();

                var oldDetails = await myDbContext.FG_Finished_Goods_Store_Details.
                    Where(srd => srd.Finished_goods_store_code == fG_Finished_Goods_Store1.Finished_goods_store_code).ToListAsync();
                var toAdd = new List<FG_Finished_Goods_Store_Details>();//新增明细
                var toUpdate = new List<FG_Finished_Goods_Store_Details>();//更新明细
                var toDel = new List<int>();//删除明细id
                var netChangeDict = new Dictionary<string, decimal>();

                foreach (var newItem in fG_Finished_Goods_Store_Details)
                {
                    //新纪录：无主键或主键不在旧列表中
                    if (newItem.Finished_goods_store_details_id == 0 ||
                        !oldDetails.Any(old => old.Finished_goods_store_details_id == newItem.Finished_goods_store_details_id))
                    {
                        toAdd.Add(newItem);
                    }
                    else
                    {
                        var oldItem = oldDetails.First(old => old.Finished_goods_store_details_id == newItem.Finished_goods_store_details_id);
                        if (IsModified(oldItem, newItem))
                        {
                            toUpdate.Add(newItem);
                        }
                    }
                }

                toDel = oldDetails.Where(old => !fG_Finished_Goods_Store_Details.Any(newItem => newItem.Finished_goods_store_details_id == old.Finished_goods_store_details_id))
                    .Select(old => old.Finished_goods_store_details_id).ToList();


                //处理删除的明细：减少预计入库数量
                foreach (var item in oldDetails.Where(d => toDel.Contains(d.Finished_goods_store_details_id)))
                {
                    if (!netChangeDict.ContainsKey(item.Pro_code))
                        netChangeDict[item.Pro_code] = 0;
                    netChangeDict[item.Pro_code] -= item.Store_qty;
                }

                //处理新增的明细：增加预计入库数量
                foreach (var item in toAdd)
                {
                    if (!netChangeDict.ContainsKey(item.Pro_code))
                        netChangeDict[item.Pro_code] = 0;
                    netChangeDict[item.Pro_code] += item.Store_qty;
                }

                //处理修改的明细：计算新旧差值
                foreach (var item in toUpdate)
                {
                    var oldQty = oldDetails
                        .FirstOrDefault(old => old.Finished_goods_store_details_id == item.Finished_goods_store_details_id)?
                        .Store_qty ?? 0;

                    if (!netChangeDict.ContainsKey(item.Pro_code))
                        netChangeDict[item.Pro_code] = 0;

                    netChangeDict[item.Pro_code] += item.Store_qty - oldQty;
                }

                //批量删除旧明细
                if (toDel.Any())
                {
                    var delItems = oldDetails.Where(d => toDel.Contains(d.Finished_goods_store_details_id));
                    myDbContext.RemoveRange(delItems);
                }

                //添加新明细
                foreach (var item in toAdd)
                {
                    item.Finished_goods_store_code = fG_Finished_Goods_Store1.Finished_goods_store_code;
                    item.Finished_goods_store_id = fG_Finished_Goods_Store1.Finished_goods_store_id;
                    await myDbContext.AddAsync(item);
                }

                //修改旧明细
                foreach (var updateItem in toUpdate)
                {
                    //myDbContext.Update(updateItem);
                    var existingDetails = oldDetails.FirstOrDefault(f => f.Finished_goods_store_details_id == updateItem.Finished_goods_store_details_id);
                    if (existingDetails != null)
                    {
                        existingDetails.Finished_goods_qty = updateItem.Finished_goods_qty;
                        existingDetails.Unqualified_qty = updateItem.Unqualified_qty;
                        existingDetails.Store_qty = updateItem.Store_qty;
                        existingDetails.Location_code = updateItem.Location_code;
                        existingDetails.Location_name = updateItem.Location_name;
                    }
                }

                //更新库存预计入库数量
                var proCodes = fG_Finished_Goods_Store_Details.Select(d => d.Pro_code).Distinct().ToList();
                var locationCodes = fG_Finished_Goods_Store_Details.Select(d => d.Location_code).Distinct().ToList();
                var stockList = await myDbContext.inv_stock
                    .Where(s => proCodes.Contains(s.pro_code)
                        && locationCodes.Contains(s.Location_Code)
                        && fG_Finished_Goods_Store.Warehouse_code.Contains(s.Warehouse_Code)
                        && fG_Finished_Goods_Store.Zone_code.Contains(s.Zone_Code))
                    .ToListAsync();

                // 字典1：以stock_id为键
                var stocksById = stockList.ToDictionary(s => s.stock_id);
                // 字典2：以pro_code为键映射到stock_id
                var stockIdByCompositeKey = stockList.ToDictionary(
                    s => $"{s.pro_code}_{s.Location_Code}",
                    s => s.stock_id
                );

                foreach (var (proCode, netChange) in netChangeDict)
                {
                    var locationGroups = fG_Finished_Goods_Store_Details
                        .Where(d => d.Pro_code == proCode)
                        .GroupBy(d => d.Location_code);

                    foreach (var group in locationGroups)
                    {
                        var locationCode = group.Key;
                        var compositeKey = $"{proCode}_{locationCode}";

                        if (stockIdByCompositeKey.TryGetValue(compositeKey, out var stockId))
                        {
                            stocksById[stockId].Stock_planned_store_qty += netChange;
                            myDbContext.Entry(stocksById[stockId]).State = EntityState.Modified;
                        }
                    }
                }
                //foreach (var (proCode, netChange) in netChangeDict)
                //{
                //    //if (stockList.TryGetValue(proCode, out var stock))
                //    //{
                //    //    stock.Stock_planned_store_qty += netChange; // 直接更新库存字段
                //    //    myDbContext.Entry(stock).State = EntityState.Modified;
                //    //}
                //}

                await myDbContext.SaveChangesAsync();
                await transaction.CommitAsync();
                return 1;
            }
            catch (Exception)
            {
                await transaction.RollbackAsync();
                return 0;
            }
        }

        /// <summary>
        /// 检查字段是否修改
        /// </summary>
        /// <param name="oldItem"></param>
        /// <param name="newItem"></param>
        /// <returns></returns>
        private bool IsModified(FG_Finished_Goods_Store_Details oldItem, FG_Finished_Goods_Store_Details newItem)
        {
            return oldItem.Finished_goods_qty != newItem.Finished_goods_qty ||
                   oldItem.Unqualified_qty != newItem.Unqualified_qty ||
                   oldItem.Store_qty != newItem.Store_qty ||
                   oldItem.Location_code != newItem.Location_code ||
                   oldItem.Location_name != newItem.Location_name ||
                   oldItem.Finished_goods_store_details_id == newItem.Finished_goods_store_details_id;
        }

        /// <summary>
        /// 根据成品入库编号查询成品入库信息
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public async Task<FG_Finished_Goods_Store> GetFG_Finished_Goods_StoreByCodeAsync(string code)
        {
            return await myDbContext.FG_Finished_Goods_Store.FirstOrDefaultAsync(f => f.Finished_goods_store_code == code);
        }

        /// <summary>
        /// 条件查询成品入库总数
        /// </summary>
        /// <param name="Warehouse_Code"></param>
        /// <param name="code"></param>
        /// <returns></returns>
        public async Task<int> Get_Finished_Goods_StoreCountAsync(string Warehouse_Code, string code, char autidStatus)
        {
            IQueryable<FG_Finished_Goods_Store> query = myDbContext.FG_Finished_Goods_Store;
            query = query.Where(fgs => fgs.Del_flag == '0');
            if (!string.IsNullOrEmpty(Warehouse_Code))
            {
                query = query.Where(fgs => fgs.Warehouse_code == Warehouse_Code);
            }
            if (!string.IsNullOrEmpty(code))
            {
                query = query.Where(fgs => fgs.Finished_goods_store_code == code);
            }
            if (autidStatus == '0' || autidStatus == '1' || autidStatus == '2')
            {
                query = query.Where(fgs => fgs.Finished_goods_store_audit_status == autidStatus);
            }
            return await query.CountAsync();
        }

        /// <summary>
        /// 根据成品入库编号查询成品入库明细
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public async Task<List<FG_Finished_Goods_Store_Details>> Get_Finished_Goods_Store_DetailsByCodeAsync(string code)
        {
            return await myDbContext.FG_Finished_Goods_Store_Details.Where(f => f.Finished_goods_store_code == code).ToListAsync();
        }

        /// <summary>
        /// 分页条件查询成品入库信息
        /// </summary>
        /// <param name="Warehouse_Code"></param>
        /// <param name="code"></param>
        /// <param name="currentPage"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public List<FG_Finished_Goods_Store_Info> Get_Finished_Goods_Store_Infos(string Warehouse_Code, string code, int currentPage, int pageSize,char autidStatus)
        {
            IQueryable<FG_Finished_Goods_Store> query = myDbContext.FG_Finished_Goods_Store;
            query = query.Where(fgs => fgs.Del_flag == '0').OrderByDescending(f => f.Create_time).ThenByDescending(f => f.Update_time);

            if (!string.IsNullOrEmpty(Warehouse_Code))
            {
                query = query.Where(fgs => fgs.Warehouse_code == Warehouse_Code);
            }
            if (!string.IsNullOrEmpty(code))
            {
                query = query.Where(fgs => fgs.Finished_goods_store_code == code);
            }
            if (autidStatus == '0' || autidStatus == '1' || autidStatus == '2')
            {
                query = query.Where(fgs => fgs.Finished_goods_store_audit_status == autidStatus);
            }
            if (currentPage != 0 && pageSize != 0)
            {
                query = query.Skip((currentPage - 1) * pageSize).Take(pageSize);
            }
            var result = query
                .Select(f => new FG_Finished_Goods_Store_Info
                {
                    Finished_goods_store_id = f.Finished_goods_store_id,
                    Finished_goods_store_code = f.Finished_goods_store_code,
                    Quality_testing_status = f.Quality_testing_status,
                    Quality_testing_by = f.Quality_testing_by,
                    Quality_testing_time = f.Quality_testing_time,
                    Finished_goods_store_rep_id = f.Finished_goods_store_rep_id,
                    Finished_goods_store_dept_id = f.Finished_goods_store_dept_id,
                    Finished_goods_store_time = f.Finished_goods_store_time,
                    Finished_goods_store_audit_by = f.Finished_goods_store_audit_by,
                    Finished_goods_store_audit_time = f.Finished_goods_store_audit_time,
                    Finished_goods_store_audit_status = f.Finished_goods_store_audit_status,
                    Finished_goods_store_audit_opinion = f.Finished_goods_store_audit_opinion,
                    Warehouse_code = f.Warehouse_code,
                    Warehouse_name = f.Warehouse_name,
                    Zone_code = f.Zone_code,
                    Zone_name = f.Zone_name,
                    Create_by = f.Create_by,
                    Create_time = f.Create_time,
                    Update_by = f.Update_by,
                    Update_time = f.Update_time,
                    Del_flag = f.Del_flag,
                    Details = f.Details.Select(details => new FG_Finished_Goods_Store_Info.FG_Finished_Goods_Store_Details
                    {
                        Finished_goods_store_details_id = details.Finished_goods_store_details_id,
                        Finished_goods_store_id = details.Finished_goods_store_id,
                        Finished_goods_store_code = details.Finished_goods_store_code,
                        Pro_name = details.Pro_name,
                        Pro_brand = details.Pro_brand,
                        Pro_code = details.Pro_code,
                        Pro_model = details.Pro_model,
                        Finished_goods_qty = details.Finished_goods_qty,
                        Measure_id = details.Measure_id,
                        Store_qty = details.Store_qty,
                        Unqualified_qty = details.Unqualified_qty,
                    }).ToList()
                }).ToList();
            return result;
        }

        /// <summary>
        /// 逻辑删除成品入库信息
        /// </summary>
        /// <param name="fG_Finished_Goods_Store"></param>
        /// <returns></returns>
        public async Task<int> FG_Finished_Goods_StoreDelAsync(FG_Finished_Goods_Store fG_Finished_Goods_Store)
        {
            using var transaction = await myDbContext.Database.BeginTransactionAsync();
            try
            {
                FG_Finished_Goods_Store fG_Finished_Goods_Store1 = await myDbContext.FG_Finished_Goods_Store
                    .FirstOrDefaultAsync(f => f.Finished_goods_store_id == fG_Finished_Goods_Store.Finished_goods_store_id);
                fG_Finished_Goods_Store1.Del_flag = fG_Finished_Goods_Store.Del_flag;
                myDbContext.Update(fG_Finished_Goods_Store1);

                var details = myDbContext.FG_Finished_Goods_Store_Details
                    .Where(f => f.Finished_goods_store_id == fG_Finished_Goods_Store1.Finished_goods_store_id).ToList();

                //减少库存预计入库数量
                //var proCodes = details.Select(d => d.Pro_code).Distinct().ToList();
                //var stocks = await myDbContext.inv_stock
                //    .Where(s => proCodes.Contains(s.pro_code))
                //    .ToDictionaryAsync(s => s.pro_code);

                //foreach (var item in details)
                //{
                //    stocks[item.Pro_code].Stock_planned_store_qty -= item.Store_qty;
                //    myDbContext.Entry(stocks[item.Pro_code]).State = EntityState.Modified; // 显式标记
                //}
                var proCodes = details.Select(d => d.Pro_code).Distinct().ToList();
                var locationCodes = details.Select(d => d.Location_code).Distinct().ToList();
                var stockList = await myDbContext.inv_stock
                    .Where(s => proCodes.Contains(s.pro_code)
                        && locationCodes.Contains(s.Location_Code)
                        && fG_Finished_Goods_Store1.Warehouse_code.Contains(s.Warehouse_Code)
                        && fG_Finished_Goods_Store1.Zone_code.Contains(s.Zone_Code))
                    .ToListAsync();

                // 字典1：以stock_id为键
                var stocksById = stockList.ToDictionary(s => s.stock_id);
                // 字典2：以pro_code为键映射到stock_id
                var stockIdByProCode = stockList.ToDictionary(s => s.pro_code, s => s.stock_id);

                foreach (var item in details)
                {
                    if (stockIdByProCode.TryGetValue(item.Pro_code, out var stockId))
                    {
                        stocksById[stockId].Stock_planned_store_qty -= item.Store_qty;
                        myDbContext.Entry(stocksById[stockId]).State = EntityState.Modified;
                    }
                }

                await myDbContext.SaveChangesAsync();
                await transaction.CommitAsync();
                return 1;
            }
            catch (Exception)
            {
                await transaction.RollbackAsync();
                return 0;
            }
        }

        /// <summary>
        /// 修改成品入库审核状态，减少库存待入库数量，增加库存数量
        /// </summary>
        /// <param name="fG_Finished_Goods_Store"></param>
        /// <returns></returns>
        public async Task<int> FG_Finished_Goods_StoreUpdateAuditAsync(FG_Finished_Goods_Store fG_Finished_Goods_Store)
        {
            using var transaction = await myDbContext.Database.BeginTransactionAsync();
            try
            {
                FG_Finished_Goods_Store fG_Finished_Goods_Store1 = await myDbContext.FG_Finished_Goods_Store
                .FirstOrDefaultAsync(f => f.Finished_goods_store_id == fG_Finished_Goods_Store.Finished_goods_store_id);
                fG_Finished_Goods_Store1.Finished_goods_store_audit_status = fG_Finished_Goods_Store.Finished_goods_store_audit_status;
                fG_Finished_Goods_Store1.Finished_goods_store_audit_by = fG_Finished_Goods_Store.Finished_goods_store_audit_by;
                fG_Finished_Goods_Store1.Finished_goods_store_audit_opinion = fG_Finished_Goods_Store.Finished_goods_store_audit_opinion;
                fG_Finished_Goods_Store1.Finished_goods_store_audit_time = fG_Finished_Goods_Store.Finished_goods_store_audit_time;
                myDbContext.FG_Finished_Goods_Store.Update(fG_Finished_Goods_Store1);
                await myDbContext.SaveChangesAsync();

                var details = myDbContext.FG_Finished_Goods_Store_Details
                    .Where(f => f.Finished_goods_store_id == fG_Finished_Goods_Store1.Finished_goods_store_id).ToList();

                //减少库存预计入库数量
                var proCodes = details.Select(d => d.Pro_code).Distinct().ToList();
                var locationCodes = details.Select(d => d.Location_code).Distinct().ToList();
                var stockList = await myDbContext.inv_stock
                    .Where(s => proCodes.Contains(s.pro_code)
                        && locationCodes.Contains(s.Location_Code)
                        && fG_Finished_Goods_Store1.Warehouse_code.Contains(s.Warehouse_Code)
                        && fG_Finished_Goods_Store1.Zone_code.Contains(s.Zone_Code))
                    .ToListAsync();

                // 字典1：以stock_id为键
                var stocksById = stockList.ToDictionary(s => s.stock_id);
                // 字典2：以pro_code为键映射到stock_id
                var stockIdByProCode = stockList.ToDictionary(s => (s.pro_code,s.Location_Code), s => s.stock_id);

                foreach (var item in details)
                {
                    if (stockIdByProCode.TryGetValue((item.Pro_code,item.Location_code), out var stockId))
                    {
                        stocksById[stockId].Stock_planned_store_qty -= item.Store_qty;
                        if (fG_Finished_Goods_Store1.Finished_goods_store_audit_status == '1')//审核状态 == 通过增加库存
                        {
                            stocksById[stockId].stock_numder += item.Store_qty;//增加库存
                        }
                        myDbContext.Entry(stocksById[stockId]).State = EntityState.Modified;
                    }
                }
                //foreach (var item in details)
                //{
                //    stocks[item.Pro_code].Stock_planned_store_qty -= item.Store_qty;//减少预计入库数量
                //    if (fG_Finished_Goods_Store1.Finished_goods_store_audit_status == '1')//审核状态 == 通过增加库存
                //    {
                //        stocks[item.Pro_code].stock_numder += item.Store_qty;//增加库存
                //    }
                //    myDbContext.Entry(stocks[item.Pro_code]).State = EntityState.Modified; // 显式标记
                //}

                await myDbContext.SaveChangesAsync();
                await transaction.CommitAsync();

                return 1;
            }
            catch (Exception)
            {
                await transaction.RollbackAsync();
                return 0;
            }
        }
    }
}
